<template>
	<div ref="container">
		<div style="position: absolute; z-index: 10" class="flex-center w100 h100" v-show="loading">
			<dv-decoration :scale="2">
				<span class="fw" style="font-size: 30px"> {{ percentComplete }}% </span>
			</dv-decoration>
		</div>
	</div>
</template>

<script setup name="ventilate">
import { DBUtil } from '@u/indexedDB'
import { useResizeObserver, THREE, GLTFloaderFn, clock, rendererFn, MapControls, mixersFn } from '@u/threeMinx'

let container = shallowRef(null), // 模型渲染的Demo节点
	renderer, //  WebGLRenderer渲染器
	scene, // 场景
	camera, // 相机
	controls,
	loading = ref(false),
	percentComplete = ref(0)

// 组件宽高
let width, height
useResizeObserver(container, (entries) => {
	width = entries[0].contentRect.width
	height = entries[0].contentRect.height
	camera.aspect = width / height
	camera.updateProjectionMatrix()
	renderer.setSize(width, height)
})
// 初始化生命周期
onMounted(() => {
	loading.value = true
	init()
})
onBeforeUnmount(() => {
	cancelAnimationFrame(requestAnimationFrameIndex)
	// 释放显存
	renderer?.dispose()
	// 释放内存
	container = null
	scene = null
})

function init() {
	// 场景
	scene = new THREE.Scene()
	// 相机
	camera = new THREE.PerspectiveCamera(45, width / height, 1, 2000)
	camera.position.set(-30.252, 24.161, -32.077)
	scene.add(camera)
	renderer = rendererFn(container)
	// 控制器
	controls = new MapControls(camera, renderer.domElement)
	controls.target.set(0, -5, 0)
	controls.minPolarAngle = 0
	controls.maxPolarAngle = Math.PI / 2
	// 灯光
	lights()
	// 加载器
	loaderFn()
}
let model,
	mixers = []
function loaderFn() {
	new DBUtil().get(`${import.meta.env.VITE_APP_BASE_BASE || '/'}model/主通风.glb`).then((blob) => {
		let url = URL.createObjectURL(blob)
		GLTFloaderFn.load(
			url,
			(object) => {
				loading.value = false
				model = object.scene
				scene.add(model)
				//动画
				mixers.push(mixersFn(object))
				render()
			},
			(xhr) => {
				if (xhr.lengthComputable) percentComplete.value = Math.round((xhr.loaded / xhr.total) * 100, 2)
			}
		)
	})
}

/**
 * 灯光
 */
function lights() {
	// 自然光
	scene.add(new THREE.AmbientLight('#ffffff', 0.5))
	let light2 = new THREE.PointLight('#ffffff', 0.5)
	light2.position.set(100, 100, -100)
	scene.add(light2)
}

// 渲染逻辑
let requestAnimationFrameIndex
function render() {
	// 运行动画
	mixers.forEach((mixer) => mixer.update(clock.getDelta() * 2))
	controls.update()
	renderer?.render(scene, camera)
	requestAnimationFrameIndex = requestAnimationFrame(render)
}
</script>
